%%%-------------------------------------------------------------------
%%% File    : pmm_default.erl
%%% Author  :  <vjache>
%%% Description : 
%%%
%%% Created : 24 Apr 2009 by  <vjache>
%%%-------------------------------------------------------------------
-module(pmm_default).

-include("../include/iter.hrl").

%% API
-export([
		 open_part_index/4,
		 close_part_index/1,
		 close_opened_partitions/2,
		 get_partition/2,
		 format/2,
		 deformat/2,
		 get_partition_by_key/2,
		 get_all_partitions/1
		 ]).

%%====================================================================
%% API Callback functions
%%====================================================================
open_part_index(VectName,RecordName,Attrs,FragProps) ->
	PiVectName=pi_vect_name(VectName),
	PiVect=vect_mnesia:new(PiVectName,
						   [{attributes, [part_key,part_id]},
							{type, set},
%% 							{record_name, RecordName},
							{record_name, PiVectName},
							{disc_copies, [node()]}
						   %,{local_content, true}
						   ]),
	{_PiVectSess=vect:open(PiVect),VectName,Attrs,_PidOwner=self(),FragProps}.
close_part_index({PiVectSess,_VectName,_Attrs,_PidOwner,FragProps}=_PMMSess) ->
	vect:close(PiVectSess).
close_opened_partitions({PiVectSess,VectName,Attrs,_PidOwner,FragProps}=_PMMSess,PidOwner) ->
	ok.
get_partition(PMMSess,Tuple) ->
	get_partition_by_key(PMMSess,element(2,Tuple)).
format(_PMMSess,Tuple)->
	[Tag,PartKey|Other]=tuple_to_list(Tuple),
	erlang:append_element(list_to_tuple([Tag|Other]),PartKey).
deformat({_PiVectSess,_VectName,_Attrs,_PidOwner,FragProps}=_PMMSess,FTuple) ->
	[Tag|Other]=tuple_to_list(FTuple),
	list_to_tuple([Tag|last_to_first(Other,[])]).

last_to_first([PartKey],Tail) ->
	[PartKey|lists:reverse(Tail)];
last_to_first([H|Other],Tail) ->
	last_to_first(Other,[H|Tail]).

get_partition_by_key({PiVectSess,VectName,Attrs,_PidOwner,FragProps}=_PMMSess,Key) ->
	PiVectName=pi_vect_name(VectName),
	Iter=vect:lookup(PiVectSess,Key),
	IState=iter:open(Iter),
	{IStateNew,PSess}=case iter:next(IState) of
						  {IStateNew,?EOF} -> 
							  <<B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16>>=erlang:md5(term_to_binary(Key)),
							  Format=lists:append(["~2.16.0B"||_<-lists:seq(1,16)]),
							  L=io_lib:format(Format,[B1,B2,B3,B4,B5,B6,B7,B8,B9,B10,B11,B12,B13,B14,B15,B16]),
							  S=atom_to_list(VectName)++lists:flatten(L),
							  PartVectName=list_to_atom(S),
							  PartVectSess=open_part_vect(PartVectName,Attrs,VectName,FragProps),
							  ok=vect:insert(PiVectSess,{PiVectName,Key,PartVectName}),
							  {IStateNew,PartVectSess};
						  {IStateNew,{PiVectName,Key,PartVectName}} ->
							  {IStateNew,open_part_vect(PartVectName,Attrs,VectName,FragProps)}
					  end,
	iter:close(IStateNew),
	PSess.

open_part_vect(PartVectName,[PartKeyAttr|OtherAttrs]=_Attrs,VectName,FragProps) ->
%% 	new(PartVectName,{disc_only,VectName,OtherAttrs++[PartKeyAttr],FragNum})
%% 	TabDefBase=[{attributes, OtherAttrs++[PartKeyAttr]},
%% 							{record_name, VectName},
%% 							{type, bag},
%% 							{disc_copies, [node()]}
%% 						   %,{local_content, true}
%% 						   ],
%% 	TabDef=case FragProps of
%% 			   undefined ->
%% 				   TabDefBase;
%% 			   Num ->
%% 				   [{frag_properties,
%% 					 [{n_fragments, Num},
%% 					  {n_disc_only_copies, 1},
%% 					  {node_pool,[node()]}
%% 					 ]}|TabDefBase]
%% 		   end,
	PartVect=vect_mnesia:new(PartVectName,{disc_only,VectName,OtherAttrs++[PartKeyAttr],FragProps}),
			vect:open(PartVect).

get_all_partitions({PiVectSess,VectName,Attrs,_PidOwner,FragProps}=_PMMSess) ->
	IterAll=vect:all(PiVectSess),
	{IterFinState,Result}=iter:fold(IterAll, 
			  fun({_PiVectName,_Key,PartVectName},SessList)->
					  PartVectSess=open_part_vect(PartVectName,Attrs,VectName,FragProps),
					  [PartVectSess|SessList]
			  end, []),
	ok=iter:close(IterFinState),
	Result.
%%====================================================================
%% Private functions
%%====================================================================
%%--------------------------------------------------------------------
%% Function: 
%% Description:
%%--------------------------------------------------------------------


pi_vect_name(VectName) ->
	list_to_atom(atom_to_list(VectName)++"pi").


%% test_mnesia() ->
%% 	Cfg=[{record_name, entry},{attributes, [a,b,c]},{disc_only_copies, [node()]},{type, bag},{frag_properties,[{n_fragments, 20},{n_disc_only_copies, 1},{node_pool,[node()]}]}],	ok=mnesia:create_table(entry, Cfg),
%% 	L=lists:seq(1, 10000000),
%% 	mnesia:activity(async_dirty, 
%% 					fun()-> 
%% 							lists:foreach(fun(I)->
%% 												  mnesia:write(
%% 													{entry,
%% 													 {aaaaaaa,I},
%% 													 {bbbbbbbbbbbbbbbbbbbb,"Qqeor6845 45ijrtnm trkjtiop rt 0430 4509 4509 450  rtweorijeopirero 9455d324r2143r243r2erewrqwrq",I},
%% 													 {'$CCCCCCCCCCCCCCCCCCCCCdsggfCCCCCCCCCCCCCCC',"skagbkdfgliuhflunxqgn7io234ty980m1834s3gmfhosefgilgnfqcwn932hf9kap0oqehidfqpfk23840pfmc4kons93410sjkfkprh3k9r7h95tjh"}
%% 													}),
%% 												  R=I rem 1000,
%% 												  case R of
%% 													  0 ->
%% 														  io:format("Loaded ~p records~n",[I]);
%% 													  _ ->
%% 														  ok
%% 												  end
%% 										  end, L)
%% 					end, [], mnesia_frag),
%% 	mnesia:activity(async_dirty, 
%% 					fun()-> 
%% 							mnesia:table_info(entry, size)
%% 					end, [], mnesia_frag),
%% 	mnesia:activity(async_dirty, 
%% 					fun()-> 
%% 							mnesia:read(entry, {aaaaaaa,333333}, read)
%% 					end, [], mnesia_frag).